using UnityEngine;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using System.Net;
using Frankfort.Threading.Internal;
using System.Threading;


enum DecompressLocalBundleMode
{
    none,
    all,
    unessential,
}


public class NewDecompressLocalBundleHelper
{
    private static string zipFilePath;
    System.Action<bool> callback;
    uint totalSize = 0;
    uint progress = 0;
    Dictionary<string, BundleInfo> needDecompressBundleMaps;

    public NewDecompressLocalBundleHelper()
	{
        CompressManager temp = CompressManager.instance;

		zipFilePath = Application.dataPath;
	}

    public Dictionary<string, BundleInfo> GetNeedDecompressBundleMap()
    {
        return needDecompressBundleMaps;
    }


    public uint GetProgress(out uint total)
    {
        total = totalSize;
        return progress;
    }

    public void Start(BundleVersionConfig config, System.Action<bool> callback)
    {
        this.callback = callback;

        if (Application.platform != RuntimePlatform.Android || SwitchConfig.decompressLocalBundleMode == DecompressLocalBundleMode.none.ToString())
        {
            callback(true);
            return;
        }

        needDecompressBundleMaps = new Dictionary<string, BundleInfo>();

        Dictionary<string, BundleInfo>.Enumerator e = config.bundles.GetEnumerator();
        while (e.MoveNext())
        {
            LocalBundleInfo localBundleInfo = null;
            bool inApp = false;
            if (BundleVersionManager.instance.isBundleExist(e.Current.Value, out localBundleInfo, out inApp))
            {
                if (localBundleInfo != null)
                {
                    if(inApp && localBundleInfo.local_type == LocalType.unessential || SwitchConfig.decompressLocalBundleMode == DecompressLocalBundleMode.all.ToString())
                    {
                        string bundleName = e.Current.Key;
                        needDecompressBundleMaps.Add(e.Current.Key, e.Current.Value);
                        totalSize += e.Current.Value.size;
                    }
                }
            }
        }


        if (needDecompressBundleMaps.Count <= 0)
        {
            callback(true);
            return;
        }

        DecompressBundles();
    }
	
    private void DecompressBundles ()
	{
		SingleThreadStarter.StartSingleThread (() =>  {
			bool ret = DecompressOrDeleteLocalBundle2 ();
			Finish(ret);
		});
	}
	
    private void Finish(bool success)
	{
		if(!Loom.CheckIfMainThread())
		{
            string log = new System.Exception().ToString();
			MainThreadDispatcher.DispatchToMainThread((object obj) => 
			                                          {
                if(!success)
                {
                    Debug.LogError("test decomporess success: " + success + "  " + testA + "  " + testB + "  " + testC);
                }

				Finish(success);
			}, null);
			return;
		}

        this.callback(success);
	}
	
    private int testA = 0;
    private bool testB;
    private string testC;
    private bool DecompressOrDeleteLocalBundle2()
	{
        Dictionary<string, BundleInfo> newDic = new Dictionary<string, BundleInfo>();
        Dictionary<string, BundleInfo>.Enumerator e = needDecompressBundleMaps.GetEnumerator();
		while(e.MoveNext())
		{
            string entryName = "assets/" + e.Current.Value.GetHashName();
            newDic.Add(entryName, e.Current.Value);
		}
		
		if(!System.IO.File.Exists(zipFilePath))
		{
            testA = 1;
            testB = false;
			return false;
		}

		bool globalRet = true;
		FileStream input = null;
		ZipInputStream zipInput = null;
		try
		{
			input = File.OpenRead(zipFilePath);
			zipInput = new ZipInputStream(input);
            int checkCount = 0;

            while(checkCount < newDic.Count)
			{
				ZipEntry entry = zipInput.GetNextEntry();

				if(entry == null)
				{
					break;
				}

                BundleInfo value = null;
                if(newDic.TryGetValue(entry.Name, out value))
				{
                    checkCount++;
                    
					bool ret = false;
					if(globalRet)
					{
                        CommonUtil.Delete(value.GetDownloadPath());

                        uint oldProgress = progress;
                        ret = CompressManager.DecompressStreamToFile(value.compress, zipInput, value.GetDownloadPath(), (p) =>
                            {
                                progress = oldProgress + p;
                            });
                        
						globalRet = ret;
//                        if(ret)
//                        {
//                            progress += value.size;
//                        }
					}

                    if(!globalRet)
                    {
                        testA = 2;
                        testC = entry.Name;
                        break;
                    }
				}
			}
		}
		catch(System.Exception e2)
		{
            testA = 3;
            testC = zipFilePath + " | " + e2.ToString();

            globalRet = false;
            Debug.LogException(e2);
		}
		finally
		{
			if(zipInput != null)
			{
				zipInput.Close();
				zipInput = null;
			}
		}
		

        testB = globalRet;
		return globalRet;
	}
}

